/**
 * 
 */
package com.thinkgsp.jxc.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgsp.jxc.model.Product;
import com.thinkgsp.jxc.model.ProductBatchNo;
import com.thinkgsp.jxc.model.ProductBusProperties;
import com.thinkgsp.jxc.model.ProductClassify;
import com.thinkgsp.jxc.model.ProductLogisticsProperties;
import com.thinkgsp.jxc.model.ProductManuf;
import com.thinkgsp.jxc.model.ProductMedicineProperties;
import com.thinkgsp.jxc.persistence.ProductBatchNoMapper;
import com.thinkgsp.jxc.persistence.ProductMapper;
import com.thinkgsp.jxc.persistence.mybatis.PagingResult;
import com.thinkgsp.jxc.service.ModelExistsException;
import com.thinkgsp.jxc.service.ProductService;
import com.thinkgsp.jxc.service.ServiceException;
import com.thinkgsp.sys.persistence.PersistenceException;

/**
 * 产品业务接口的实现类
 * 提供产品、产品生产企业、产品分类的持久化与搜索功能
 * @author evan
 *
 */
@Service("productService")
@Transactional
public class ProductServiceImpl extends GeneralServiceImpl implements
		ProductService {

	@Autowired
	private ProductMapper productMapper;
	@Autowired
	private ProductBatchNoMapper batchNoMapper;
	
	
	
	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#setProductMapper(com.thinkgsp.jxc.persistence.ProductMapper)
	 */
	public void setProductMapper(ProductMapper productMapper) {
		this.productMapper = productMapper;
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#saveProduct(com.thinkgsp.jxc.model.Product)
	 */
	public void saveProduct(Product product) throws ModelExistsException,PersistenceException {
		try {
			if(product.getProductId() == null || product.getProductId() == 0) {
				productMapper.insertProduct(product);
				if(!product.isBatchMgr()) {
					ProductBatchNo batchNo = new ProductBatchNo();
					batchNo.setBatchNo(ProductBatchNo.NON_BATCH_MGR_VALUE);
					batchNo.setProductId(product.getProductId());
					batchNoMapper.insertBatchNo(batchNo);
				}
				ProductBusProperties pbp = product.getProductBusProperties();
				if(pbp == null) {
					pbp = new ProductBusProperties();
				}
				pbp.setProductId(product.getProductId());
				productMapper.insertBusProperties(pbp);
				
				ProductMedicineProperties pmp = product.getProductMedicineProperteis();
				if(pmp == null) {
					pmp = new ProductMedicineProperties();
				}
				pmp.setProductId(product.getProductId());
				productMapper.insertMedicineProperties(pmp);
				
				ProductLogisticsProperties plp = product.getProductLogisticsProperties();
				if(plp == null) {
					plp = new ProductLogisticsProperties();
				}
				plp.setProductId(product.getProductId());
				productMapper.insertLogisticsProperties(plp);
			} else {
				
				
				productMapper.updateProduct(product);
				
				
				
				Product p =this.getProduct(product.getProductId());
				
				if(!product.isBatchMgr()) {
					ProductBatchNo bn=batchNoMapper.getBatchNoByProduct(product.getProductId(),ProductBatchNo.NON_BATCH_MGR_VALUE);
					if(bn==null){
						ProductBatchNo batchNo = new ProductBatchNo();
						batchNo.setBatchNo(ProductBatchNo.NON_BATCH_MGR_VALUE);
						batchNo.setProductId(product.getProductId());
						batchNoMapper.insertBatchNo(batchNo);
					}
				}
				
				if(product.getProductBusProperties() != null) {
					if(p.getProductBusProperties() == null) {
						productMapper.insertBusProperties(product.getProductBusProperties());
					} else {
						productMapper.updateBusProperties(product.getProductBusProperties());
					}
				}
				if(product.getProductMedicineProperteis() != null) {
					if(p.getProductMedicineProperteis() == null) {
						productMapper.insertMedicineProperties(product.getProductMedicineProperteis());
					} else {
						productMapper.updateMedicineProperties(product.getProductMedicineProperteis());
					}
				}
				if(product.getProductLogisticsProperties() != null) {
					if(p.getProductLogisticsProperties() == null) {
						productMapper.insertLogisticsProperties(product.getProductLogisticsProperties());
					} else {
						productMapper.updateLogisticsProperties(product.getProductLogisticsProperties());
					}
				}
			}
		} catch(DuplicateKeyException e) {
			log.warn(e);
			throw new ModelExistsException("产品:'" + product.getProductCode() + "'已经存在。");
		} catch(Exception e) {
			log.error(e);
			throw new PersistenceException("产品:'" + product.getProductName() + "'保存失败。");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#disableProduct(java.lang.Integer)
	 */
	public void disableProduct(Integer productId) {
		productMapper.disableProduct(productId);
		log.info("Product Id: " + productId + " disabled.");
	}
	
	public void enableProduct(Integer productId) {
		productMapper.enableProduct(productId);
		log.info("Product Id: " + productId + " enabled.");
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#getAllProductManuf()
	 */
	public List<ProductManuf> getAllProductManuf() {
		return productMapper.getAllManuf();
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#getProductManuf(java.lang.Integer)
	 */
	public ProductManuf getProductManuf(Integer manufId) {
		return productMapper.getManuf(manufId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#searchProductManuf(java.lang.String)
	 */
	public List<ProductManuf> searchProductManuf(String val) {
		return productMapper.searchManuf(val);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#saveProductManuf(com.thinkgsp.jxc.model.ProductManuf)
	 */
	public void saveProductManuf(ProductManuf productManuf) throws ModelExistsException,PersistenceException {
		try {
			if(productManuf.getManufId() == null || productManuf.getManufId() == 0) {
				productMapper.insertManuf(productManuf);
			} else {
				productMapper.updateManuf(productManuf);
			}
		} catch(DuplicateKeyException e) {
			log.error(e.getMessage());
			throw new ModelExistsException("产品生产企业:'" + productManuf.getManufId() + "' 已经存在");
		} catch(Exception e) {
			log.error(e);
			throw new PersistenceException("产品生产企业保存失败：" + e.getMessage());
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#deleteProductManuf(java.lang.Integer)
	 */
	public void deleteProductManuf(Integer manufId) {
		productMapper.deleteManuf(manufId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#saveProductClassify(com.thinkgsp.jxc.model.ProductClassify)
	 */
	public void saveProductClassify(ProductClassify productClassify) throws ModelExistsException,PersistenceException {
		try {
			if(productClassify.getClassifyId() == null || productClassify.getClassifyId() == 0) {
				productMapper.insertClassify(productClassify);
			} else {
				productMapper.updateClassify(productClassify);
			}
		} catch(DuplicateKeyException e) {
			log.warn(e.getMessage());
			throw new ModelExistsException("产品分类:" + productClassify.getClassifyId() + "' 已经存在。");
		} catch(Exception e) {
			log.error(e);
			throw new PersistenceException("产品分类:" + productClassify.getClassifyId() + "'保存失败。");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#deleteProductClassify(java.lang.Integer)
	 */
	public void deleteProductClassify(Integer classifyId) throws ServiceException {
		List<ProductClassify> childs = productMapper.getClassifyChilds(classifyId);
		if(childs != null && childs.size() > 0) {
			throw new ServiceException("分类ID:'" + classifyId + "' 包含有子分类，不能删除。");
		} else {
			productMapper.deleteClassify(classifyId);
		}

	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#getProductClassify(java.lang.Integer)
	 */
	public ProductClassify getProductClassify(Integer classifyId) {
		//return productMapper.getClassify(classifyId);
		return loadProductClassify(classifyId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.ProductService#getProductClassifyTree()
	 */
	public ProductClassify getProductClassifyTree() {
		ProductClassify root = loadProductClassify(1);
		return root;
	}
	

	private ProductClassify loadProductClassify(Integer classifyId) {
		ProductClassify pc = productMapper.getClassify(classifyId);
		if(pc != null) {
			List<ProductClassify> childs = productMapper.getClassifyChilds(pc.getClassifyId());
			pc.getChilds().addAll(childs);
			for(ProductClassify child : childs) {
				ProductClassify c = loadProductClassify(child.getClassifyId());
				child.getChilds().addAll(c.getChilds());
			}
		}
		return pc;
	}

	public Product getProduct(Integer productId) {
		return productMapper.getAllPropertiesProduct(productId);
	}
	
	public List<Product> getDeletedProducts() {
		return productMapper.getDeletedProducts();
	}

	public List<Product> searchProducts(String val) {
		if(val != null) {
			val = val.toUpperCase();
		}
		return productMapper.searchProduct(val);
	}
	
	public PagingResult<Product> searchProducts(String val,int start,int size) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("val", val);
		RowBounds rows = new RowBounds(start, size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.ProductMapper.searchProductCount", 
				"com.thinkgsp.jxc.persistence.ProductMapper.searchProductPaging", 
				map, rows);
	}
	
	public List<Product> getProductsByClassifyId(int classifyId) {
		//return productMapper.getProductByClassifyId(classifyId);
		ProductClassify pc = loadProductClassify(classifyId);
		List<Product> list = new ArrayList<Product>();
		loadProductByClassify(list, pc);
		return list;
	}
	
	private void loadProductByClassify(List<Product> list,ProductClassify pc) {
		List<Product> childs = productMapper.getProductByClassifyId(pc.getClassifyId());
		if(childs != null && childs.size() > 0) {
			list.addAll(childs);
		}
		for(ProductClassify child : pc.getChilds()) {
			loadProductByClassify(list, child);
		}
	}
	
	public List<Product> getProductsByManufId(int manufId) {
		return productMapper.getProductByManufId(manufId);
	}
	public String convertChineseToPinYin(String chs) {
		return productMapper.convertChineseToPinYin(chs);
	}

	public PagingResult<Product> getDeletedProductsPaging(RowBounds rows) {
		PagingResult<Product> list = new PagingResult<Product>();
		HashMap<String, Object> map = new HashMap<String, Object>();
		list = queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.ProductMapper.deletedProductCount", 
				"com.thinkgsp.jxc.persistence.ProductMapper.getDeletedProductsPaging", 
				map, rows);
		return list;
	}

	public PagingResult<Product> getProductsByClassifyId(int classifyId,
			int start, int size) {
		ProductClassify pc = loadProductClassify(classifyId);
		List<Integer> ids = new ArrayList<Integer>();
		foreachClassifyIds(pc,ids);
		
		PagingResult<Product> list = new PagingResult<Product>();
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("classifyIds", ids);
		RowBounds rows = new RowBounds(start, size);
		list = queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.ProductMapper.getProductByClassifyIdCount", 
				"com.thinkgsp.jxc.persistence.ProductMapper.getProductByClassifyIdPaging", 
				map, rows);
		return list;	
	}
	
	private void foreachClassifyIds(ProductClassify parent,List<Integer> ids) {
		ids.add(parent.getClassifyId());
		for(ProductClassify child : parent.getChilds()) {
			if(child.getChilds() != null && child.getChilds().size() > 0) {
				foreachClassifyIds(child,ids);
			} else {
				ids.add(child.getClassifyId());
			}
		}
	}

}
